from scapy.all import *
import gmssl.sm3 as sm3
import datetime
from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT
import sys


# 字符串 data 进行hash 得到定长字符串
def my_hash(data):
    b = str(data)
    if len(b) % 2 != 0:
        b += "0"
    ans_list = []
    for i in range(int(len(b) / 2)):
        temp = b[i * 2:i * 2 + 2].encode('utf-8')
        ans_list.append(sm3.sm3_kdf(temp, 2))
    ans = ""
    for i in ans_list:
        ans += i
    end = ans[len(ans) - 1] + ans[0] + ans[int(len(ans) / 3)] + ans[int(len(ans) / 2)]
    return end

def to_bytes(data):
    if isinstance(data, str):
        if len(data) % 2 != 0:
            data += '0'
            print("add '0' at end,amended: ", end="")
            print(data)
        return bytes().fromhex(data)
    elif isinstance(data, list):
        return bytes(data)
    else:
        print("only 'str' or 'list' is valid!")
        return None


def decrypt(massage, key):
    key = bytes(key, encoding='utf-8')
    sm4 = CryptSM4()
    sm4.set_key(key, SM4_DECRYPT)
    decrypt_value = sm4.crypt_ecb(to_bytes(massage))  # bytes类型
    return decrypt_value.decode(encoding='utf-8')  # 返回str

pkt_list = []

def chk_sum2(a):
    b = str(a)
    length = len(b)
    if len(b) % 2 != 0:
        b += "0"
    ans_list = []
    for i in range(int(len(b) / 2)):
        temp = b[i * 2:i * 2 + 2].encode('utf-8')

        ans_list.append(sm3.sm3_kdf(temp, 20))
    ans = ""
    for i in ans_list:
        for j in range(2):
            temp2 = str(i[j])
            temp_list = ['a', 'b', 'c', 'd', 'e', 'f']
            if temp2 in temp_list:
                temp2 = str(temp_list.index(temp2))
            ans += temp2

    return ans

def chk_sum(a):
    b = str(a)
    length=len(b)
    if len(b) % 2 != 0:
        b += "0"
    ans_list = []
    for i in range(int(len(b) / 2)):
        temp = b[i * 2:i * 2 + 2].encode('utf-8')

        ans_list.append(sm3.sm3_kdf(temp, 1))
    ans = ""
    for i in ans_list:
        for j in range(2):
            temp2=str(i[j])

            temp_list = ['a','b','c','d','e','f']
            if temp2 in temp_list:
                temp2=str(temp_list.index(temp2))
            ans += temp2

    end = ""
    for i in range(length):
        end += ans[len(ans) - 1] + ans[0] + ans[int(len(ans) / 3)] + ans[int(len(ans) / 2)]
    return ans


def get_key( pkt_list, pkt_end ):
    time_list = []
    data_list=""
    for i in pkt_list:
        data_list+=str(i['Raw'].load).split('?')[1].split('&')[1][2:]
        time_list.append(i.time)
    #取出尾包的校验信息
    chesum = ""
    for i in pkt_end:
        chesum+=str(i['Raw'].load).split('?')[1].split('&')[1][2:]
    #取出秘密信息
    data = []
    b_datetime_struct = datetime.datetime.fromtimestamp(time_list[0])
    for i in range(1, len(time_list)):
        e_datetime_struct = datetime.datetime.fromtimestamp(time_list[i])
        data.append((e_datetime_struct - b_datetime_struct).total_seconds())
        b_datetime_struct = e_datetime_struct
    bin_string = ""
    for i in data:
        if (i * 100 % 100 > 50):
            print("延时过高，重传！")
        else:
            bin_string += pool[int(i) - 1]
    word_list = []
    for i in range(int(len(bin_string) / 8)):
        if bin_string[i * 8:i * 8 + 8] != '00000000':
            word_list.append(bin_string[i * 8:i * 8 + 8])
    #获取秘钥
    key = ""
    #print(word_list)
    for i in word_list:
        key += chr(int(i, 2))
    print("解码得到秘钥=", key)
    #进行完整性校验
    if my_hash(data_list) != chesum:
        print("完整性校验失败，重传！")
    #解密
    keyy=key+"1111111111111111"
    print("解密得到信息为：", decrypt(data_list,keyy))

    sys.exit(0)

 
def  check_pkt(packet):

    global pkt_list
    if chk_sum(packet['TCP'].seq) == str(packet["TCP"].ack):
        pkt_list.append(packet)
    if chk_sum(packet['TCP'].sport) == str(packet["TCP"].ack):
        get_key(pkt_list,packet)


pool=['000', '001', '010', '011', '100', '101', '110', '111']

packet = sniff(iface='Intel(R) Wireless-AC 9560 160MHz',prn=check_pkt, lfilter=lambda p: "GET" in str(p), filter="tcp port 80")




